package org.springframework.boot.aa;

import java.math.BigDecimal;
import java.util.*;

/**
 * TODO 类功能介绍及重点或容易混淆点的说明。
 *
 * @version 1.0 2023/4/13 22:22 龙小南 新建类[说明]
 * @author: 龙小南
 * @Date: 2023/4/13 22:22
 * @Version 1.0[当前版本号]
 */

public class Aa {
    public static void main(String[] args) {
        Map<String, String> map1 = Map.of(
                "起始金额", "0"
                , "截至金额", "300"
                , "费率", "4"
                , "index", "1");
        Map<String, String> map2 = Map.of(
                "起始金额", "300"
                , "截至金额", "600"
                , "费率", "3.5"
                , "index", "2");
        Map<String, String> map3 = Map.of(
                "起始金额", "600"
                , "截至金额", "-1"
                , "费率", "3"
                , "index", "3");
        List<Map<String, String>> list = new ArrayList<>();
        list.add(map2);
        list.add(map1);
        list.add(map3);

        // {3=50, 3.5=300, 4=100}
//        Map<BigDecimal, BigDecimal> getss = getss(BigDecimal.valueOf(200), BigDecimal.valueOf(450), list);
        // {3=400, 3.5=200}
//        Map<BigDecimal, BigDecimal> getss = getss(BigDecimal.valueOf(400), BigDecimal.valueOf(600), list);

        Map<BigDecimal, BigDecimal> getss = stepRateAndPercentAmount(java.math.BigDecimal.valueOf(10), java.math.BigDecimal.valueOf(301), list);
        System.out.println(getss);
    }

    /**
     * 阶梯费率，固定金额
     * @param billingBase 计费基数
     * @param ratingValueList
     */
    private static void stepRateAndStationaryAmount(BigDecimal billingBase, List<Map<String, String>> ratingValueList){
        for (int i = 0; i < ratingValueList.size(); i++) {
            // 获取到阶梯数据
            Map<String, String> ratingValueMap = ratingValueList.get(i);
            BigDecimal rate = BigDecimalUtil.valueOf(ratingValueMap.get("费率"));
            BigDecimal leftAmount = BigDecimalUtil.valueOf(ratingValueMap.get("起始金额"));
            BigDecimal rightAmount = BigDecimalUtil.valueOf(ratingValueMap.get("截至金额"));
            BigDecimal betweenAmount = BigDecimalUtil.subtract(rightAmount, leftAmount);
            if (BigDecimalUtil.equals(rightAmount, new BigDecimal("-1"))) {
                rightAmount = BigDecimal.valueOf(Integer.MAX_VALUE);
            }
        }
    }

    /**
     * 阶梯费率，百分比金额
     * @param historyAmount
     * @param nowAmount
     * @param ratingValueList
     * @return
     */
    private static Map<BigDecimal, BigDecimal> stepRateAndPercentAmount(BigDecimal historyAmount, BigDecimal nowAmount, List<Map<String, String>> ratingValueList) {
        BigDecimal totalAmount = historyAmount.add(nowAmount);
        // 根据排序key 把费率规则list从大到小重新排序
        ratingValueList.sort(Comparator.comparing(o -> o.get("index").toString()));
        Collections.reverse(ratingValueList);

        Map<BigDecimal, BigDecimal> map = new TreeMap<>();

        int a = 0;
        // 剩余未匹配阶梯的计费金额
        BigDecimal remAmount = BigDecimal.ZERO;
        for (int i = 0; i < ratingValueList.size(); i++) {
            // 获取到阶梯数据
            Map<String, String> ratingValueMap = ratingValueList.get(i);
            BigDecimal rate = BigDecimalUtil.valueOf(ratingValueMap.get("费率"));
            BigDecimal leftAmount = BigDecimalUtil.valueOf(ratingValueMap.get("起始金额"));
            BigDecimal rightAmount = BigDecimalUtil.valueOf(ratingValueMap.get("截至金额"));
            BigDecimal betweenAmount = BigDecimalUtil.subtract(rightAmount, leftAmount);
            if (BigDecimalUtil.equals(rightAmount, new BigDecimal("-1"))) {
                rightAmount = BigDecimal.valueOf(Integer.MAX_VALUE);
            }

            // 如果 totalAmount 小于 rightAmount，说明本阶梯还不能计费，需跳过本阶梯
            if (totalAmount.compareTo(leftAmount) < 0) {
                a++;
                continue;
            }
            // 第一次计费，需要通过总金额(totalAmount)字段来计算
            if (a == i) {
                BigDecimal subTotalAmount = BigDecimalUtil.subtract(totalAmount, leftAmount);
                BigDecimal amount = BigDecimalUtil.min(subTotalAmount, nowAmount);
                remAmount = getRemAmount(nowAmount, amount, map, rate);
                continue;
            }
            // 第2.3...次计费，需要通过剩余金额(remAmount)字段来计算
            if (remAmount.compareTo(betweenAmount) > 0) {
                BigDecimal amount = betweenAmount;
                remAmount = getRemAmount(remAmount, amount, map, rate);
            } else {
                BigDecimal amount = remAmount;
                remAmount = getRemAmount(remAmount, amount, map, rate);
            }
        }
        return map;
    }

    private static BigDecimal getRemAmount(BigDecimal nowAmount, BigDecimal amount, Map<BigDecimal, BigDecimal> map, BigDecimal rate) {
        BigDecimal remAmount;
        if (amount.compareTo(BigDecimal.ZERO) > 0) {
            map.put(rate, amount);
        }
        remAmount = BigDecimalUtil.subtract(nowAmount, amount);
        return remAmount;
    }
}
